/*
 *  Copyright 2011 yura.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.vcforms.transform_t2d.content;

import org.opu.vcforms.template.bean.Content;

/**
 *
 * @author yura
 */
public class ContentSqlPreparator {
    public static final char SCREEN_CHAR = '\\';

    private ContentAPI content;

    public ContentSqlPreparator(ContentAPI content) {
        this.content = content;
    }

    /**
     *  Processes the request, replacing the regular expressions 
     * substitution from the actual values. The regular expressions
     * can be: {@link Content#CALL_SUPER}, {@link Content#CALL_NEXT}
     * and {@link Content#CALL_GET}.
     *
     *  Character {@link #SCREEN_CHAR} screen special char, but
     * if next char after it not special, it`s will be added to result.
     *
     * @param query input query.
     * @return result.
     * @throws IllegalArgumentException if any problems with getting data
     * from content.
     */
    public String parseQuery(String query) throws IllegalArgumentException{
        StringBuilder result = new StringBuilder();
        char[] chars = query.toCharArray();

        Boolean wasScreenChar = false;
        boolean inRegExp = false;
        ContentAPI tmp = content;

        for (int i = 0; i < chars.length; i++) {
            boolean b = ifIn(chars[i], Content.CALL_GET, Content.CALL_NEXT, Content.CALL_SUPER);

            // if previous was expresion, but current not - to default
            if (!b && inRegExp){
                inRegExp = false;
                tmp = content;
            }

            // parse screens
            if (wasScreenChar){
                if (b) {
                    result.append(chars[i]);
                } else {
                    result.append(SCREEN_CHAR).append(chars[i]);
                }
                wasScreenChar = false;
                continue;
            }

            if (chars[i] == SCREEN_CHAR){
                wasScreenChar = true;
                continue;
            }

            // parse regular expresion
            if (b) {
                // if it first entry.
                if (!inRegExp){
                    inRegExp = true;
                    tmp = content;
                }

                // try to recognize, type of expresion, and act according to it
                String bMsg = "at " + i + " position"; // base error message
                switch (chars[i]){
                    case Content.CALL_GET:
                        try {
                            result.append(String.valueOf(tmp.last()));
                        } catch (Exception e) {
                            String msg = bMsg + " (last result of data getting of content)";
                            throw new IllegalArgumentException(msg, e);
                        }
                        break;
                    case Content.CALL_NEXT:
                         try {
                            result.append(String.valueOf(tmp.next()));
                        } catch (Exception e) {
                            String msg = bMsg + " (Cause next of content, that available only for content)";
                            throw new IllegalArgumentException(msg, e);
                        }
                        break;
                    case Content.CALL_SUPER:
                         try {
                            tmp = tmp.getParent();
                        } catch (Exception e) {
                            String msg = bMsg + " (turn to upper content - super)";
                            throw new IllegalArgumentException(msg, e);
                        }
                        break;
                }
            } else {
                result.append(chars[i]);
            }
        }

        return result.toString();
    }

    /**
     *  Return true if compare in compares.
     * @param compare vavalue for comparison.
     * @param compares an array of original values, which will compare.
     * @return true if compare in compares.
     */
    public final boolean ifIn(char compare, char... compares){
        for (int i = 0; i < compares.length; i++) {
            if (compare == compares[i]){
                return true;
            }
        }
        
        return false;
    }
}
